import pandas as pd
import numpy as np
from sklearn.ensemble import RandomForestClassifier
from sklearn.preprocessing import StandardScaler, OneHotEncoder
from sklearn.compose import ColumnTransformer
from sklearn.pipeline import Pipeline
from sklearn.metrics import classification_report
import os
from pathlib import Path

# 导入配置
from config import (
    TRAIN_DATA_PATH, TEST_DATA_PATH, OUTPUT_FILE,
    FEATURE_MAPPING, MODEL_CONFIG, VALUE_WEIGHTS,
    VALUE_THRESHOLDS, RISK_THRESHOLDS, ADJUSTMENT_FACTORS
)

# ---------------------- 数据加载与预处理 ----------------------
def load_data():
    """加载训练和测试数据"""
    try:
        print(f"正在加载训练数据: {TRAIN_DATA_PATH}")
        train_df = pd.read_csv(TRAIN_DATA_PATH)
        print(f"训练数据加载成功，共{len(train_df)}条记录")
        
        print(f"正在加载测试数据: {TEST_DATA_PATH}")
        test_df = pd.read_csv(TEST_DATA_PATH)
        print(f"测试数据加载成功，共{len(test_df)}条记录")
        
        return train_df, test_df
    except FileNotFoundError as e:
        print(f"文件未找到: {e}")
        print("请检查数据文件路径是否正确")
        raise
    except Exception as e:
        print(f"数据加载失败: {e}")
        raise

# 加载数据
train_df, test_df = load_data()





# 重命名测试数据特征
test_df = test_df.rename(columns=FEATURE_MAPPING)
print(f"特征映射完成: {list(FEATURE_MAPPING.keys())} -> {list(FEATURE_MAPPING.values())}")

# 选择训练特征和目标变量
train_features = ['信用分', '国家', '性别', '年龄', '任期', '余额', '银行产品编号', '信用卡', '活跃成员', '估计薪水']
target = '流失率'

# 确保测试数据只包含训练数据中存在的特征
available_test_features = [f for f in train_features if f in test_df.columns]

# ---------------------- 客户价值计算 ----------------------
def calculate_customer_value(row):
    """优化的客户价值计算（多维度评估）"""
    try:
        # 基础价值计算
        base_value = (
            row['余额'] * VALUE_WEIGHTS['balance_weight'] + 
            row['估计薪水'] * VALUE_WEIGHTS['salary_weight'] + 
            row['银行产品编号'] * VALUE_WEIGHTS['products_multiplier'] * VALUE_WEIGHTS['products_weight']
        )
        
        # 调整因子
        adjustment_factor = 1.0
        
        # 信用分调整
        if row['信用分'] > ADJUSTMENT_FACTORS['credit_score_high']:
            adjustment_factor += ADJUSTMENT_FACTORS['credit_adjustment']
        elif row['信用分'] < ADJUSTMENT_FACTORS['credit_score_low']:
            adjustment_factor -= ADJUSTMENT_FACTORS['credit_adjustment']
            
        # 活跃状态调整
        if row['活跃成员'] == 1:
            adjustment_factor += ADJUSTMENT_FACTORS['active_adjustment']
        else:
            adjustment_factor -= ADJUSTMENT_FACTORS['active_adjustment']
            
        # 信用卡持有调整
        if row['信用卡'] == 1:
            adjustment_factor += ADJUSTMENT_FACTORS['credit_card_adjustment']
            
        # 任期调整（长期客户）
        if row['任期'] > ADJUSTMENT_FACTORS['tenure_threshold']:
            adjustment_factor += ADJUSTMENT_FACTORS['tenure_adjustment']
            
        return base_value * adjustment_factor
    except Exception as e:
        print(f"客户价值计算错误: {e}")
        return 0

# 计算训练集客户价值
train_df['客户价值'] = train_df.apply(calculate_customer_value, axis=1)

# 计算测试集客户价值
test_df['客户价值'] = test_df.apply(calculate_customer_value, axis=1)

def value_stratification(value):
    """客户价值分层"""
    if value > VALUE_THRESHOLDS['high_value']:
        return '高价值'
    elif value > VALUE_THRESHOLDS['medium_value']:
        return '中价值'
    else:
        return '低价值'

train_df['价值分层'] = train_df['客户价值'].apply(value_stratification)
test_df['价值分层'] = test_df['客户价值'].apply(value_stratification)

# ---------------------- 模型训练 ----------------------
# 定义预处理管道
numeric_features = ['信用分', '年龄', '任期', '余额', '估计薪水']
categorical_features = ['国家', '性别']

preprocessor = ColumnTransformer(
    transformers=[
        ('num', StandardScaler(), numeric_features),
        ('cat', OneHotEncoder(drop='first'), categorical_features)
    ])

# 创建成本敏感模型（基于价值分层调整类别权重）
class_weights = {
    '高价值': {'0': 1, '1': 5},  # 高价值客户流失的惩罚权重更高
    '中价值': {'0': 1, '1': 2},
    '低价值': {'0': 1, '1': 1}
}

# 创建模型管道
print("正在创建机器学习模型...")
model = Pipeline([
    ('preprocessor', preprocessor),
    ('classifier', RandomForestClassifier(**MODEL_CONFIG))
])
print(f"模型配置: {MODEL_CONFIG}")

# 训练模型
print("正在训练机器学习模型...")
X_train = train_df[train_features]
y_train = train_df[target]
print(f"训练特征: {train_features}")
print(f"训练样本数: {len(X_train)}")
print(f"正样本数: {sum(y_train)}，负样本数: {len(y_train) - sum(y_train)}")

model.fit(X_train, y_train)
print("模型训练完成！")

# ---------------------- 预测与干预策略生成 ----------------------
print("\n正在进行客户流失预测...")
# 在测试集上进行预测
X_test = test_df[available_test_features]
print(f"测试样本数: {len(X_test)}")
print(f"可用特征: {available_test_features}")

test_df['流失概率'] = model.predict_proba(X_test)[:, 1] * 100  # 转换为百分比
print("流失概率预测完成！")

print("正在生成干预策略...")

def generate_strategy(row):
    """基于风险-价值矩阵的干预策略生成"""
    # 根据配置的阈值确定风险等级
    risk_probability = row['流失概率'] / 100  # 转换为小数
    if risk_probability > RISK_THRESHOLDS['high_risk']:
        risk_level = '高风险'
    elif risk_probability > RISK_THRESHOLDS['medium_risk']:
        risk_level = '中风险'
    else:
        risk_level = '低风险'
    
    # 基于风险-价值矩阵的干预策略
    strategy_matrix = {
        '高风险-高价值': '专属客户经理一对一服务; 定制化产品方案; 紧急挽留计划',
        '高风险-中价值': '发送个性化挽留邮件; 提供产品升级优惠; 电话回访',
        '高风险-低价值': '自动化营销活动; 提供基础产品优惠; 短信关怀',
        '中风险-高价值': '定期关怀电话; 推荐高端理财产品; VIP服务升级',
        '中风险-中价值': '提供高息定期存款产品; 邀请参加会员互动活动',
        '中风险-低价值': '发送产品推荐短信; 提供小额贷款优惠',
        '低风险-高价值': '维持现有服务质量; 推荐投资理财产品; 定期市场分析',
        '低风险-中价值': '定期发送理财建议; 提供积分奖励活动',
        '低风险-低价值': '基础服务维护; 节日问候和小礼品'
    }
    
    strategy_key = f'{risk_level}-{row["价值分层"]}'
    return strategy_matrix.get(strategy_key, '标准客户服务')

test_df['干预策略'] = test_df.apply(generate_strategy, axis=1)
print("干预策略生成完成！")

print("正在生成属性改善建议...")

# 增强的属性针对性建议
def generate_attribute_strategy(row):
    suggestions = []
    
    # 余额相关建议
    if row['余额'] == 0:
        suggestions.append('紧急关注：零余额客户，建议立即联系了解情况')
    elif row['余额'] < 10000:
        suggestions.append('提供高息定期存款产品，鼓励增加存款')
    elif row['余额'] > 200000:
        suggestions.append('推荐高端理财产品和投资咨询服务')
    
    # 产品数量建议
    if row['银行产品编号'] == 1:
        suggestions.append('推荐附加产品：信用卡、理财产品或保险')
    elif row['银行产品编号'] >= 4:
        suggestions.append('产品整合建议：优化产品组合，提供一站式服务')
    
    # 活跃状态建议
    if row['活跃成员'] == 0:
        suggestions.append('激活策略：邀请参加会员互动活动，提供专属优惠')
    
    # 任期建议
    if row['任期'] < 1:
        suggestions.append('新客户关怀：提供入门指导和新客户专享优惠')
    elif row['任期'] < 2:
        suggestions.append('提供长期合作优惠政策，增强客户粘性')
    elif row['任期'] > 8:
        suggestions.append('忠诚客户奖励：提供长期客户专属权益')
    
    # 信用分建议
    if row['信用分'] < 600:
        suggestions.append('信用提升建议：提供信用管理咨询和改善方案')
    elif row['信用分'] > 800:
        suggestions.append('优质信用奖励：提供低息贷款和高额度信用产品')
    
    # 年龄相关建议
    if row['年龄'] < 30:
        suggestions.append('年轻客户专案：推荐理财入门产品和职业发展贷款')
    elif row['年龄'] > 55:
        suggestions.append('退休规划建议：提供养老理财和保险产品')
    
    # 信用卡建议
    if row['信用卡'] == 0:
        suggestions.append('信用卡推荐：根据消费习惯推荐合适的信用卡产品')
    
    return '; '.join(suggestions) if suggestions else '客户状况良好，维持现有服务水平'

test_df['属性干预建议'] = test_df.apply(generate_attribute_strategy, axis=1)
print("属性改善建议生成完成！")

# ---------------------- 结果输出 ----------------------
def save_results():
    """保存预测结果"""
    try:
        print("正在生成预测结果...")
        output_cols = ['客户ID', '信用分', '客户价值', '价值分层', '流失概率', '干预策略', '属性干预建议']
        result = test_df[output_cols].round(2)
        
        # 保存到配置的输出文件
        result.to_csv(OUTPUT_FILE, index=False, encoding='utf-8-sig')
        
        # 统计信息
        total_customers = len(result)
        high_value_count = sum(result["价值分层"] == "高价值")
        medium_value_count = sum(result["价值分层"] == "中价值")
        low_value_count = sum(result["价值分层"] == "低价值")
        
        high_risk_count = sum(result["流失概率"] > RISK_THRESHOLDS['high_risk'] * 100)
        medium_risk_count = sum((result["流失概率"] > RISK_THRESHOLDS['medium_risk'] * 100) & 
                               (result["流失概率"] <= RISK_THRESHOLDS['high_risk'] * 100))
        
        print(f"\n=== 预测完成 ===")
        print(f"结果已保存至: {OUTPUT_FILE}")
        print(f"\n=== 统计信息 ===")
        print(f"总客户数: {total_customers}")
        print(f"高价值客户: {high_value_count}人 ({high_value_count/total_customers*100:.1f}%)")
        print(f"中价值客户: {medium_value_count}人 ({medium_value_count/total_customers*100:.1f}%)")
        print(f"低价值客户: {low_value_count}人 ({low_value_count/total_customers*100:.1f}%)")
        print(f"\n高风险客户: {high_risk_count}人 ({high_risk_count/total_customers*100:.1f}%)")
        print(f"中风险客户: {medium_risk_count}人 ({medium_risk_count/total_customers*100:.1f}%)")
        
        return result
    except Exception as e:
        print(f"结果保存失败: {e}")
        raise

# 执行预测和保存结果
if __name__ == "__main__":
    result = save_results()